package sjc;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class CacehWatchTest {

    static final int SESSION_OUTTIME = 5000;//ms

    public static void main(String[] args) {
        //1 重试策略：初次间隔时间为1s 重试 10次
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
        //2 通过工厂创建连接
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("192.168.72.133:2181")
                .sessionTimeoutMs(SESSION_OUTTIME)
                .retryPolicy(retryPolicy)
                .build();


    }


    /**
     * Path Cache用来观察ZNode的子节点，如果ZNode的子节点被创建、更新、删除，那么Path Cache会更新缓存，并且触发事件给注册的监听器。
     * Path Cache是通过PathChildrenCache类来实现的，监听器注册是通过PathChildrenCacheListener。
     * @param client
     * @throws Exception
     */
    public void pathChildrenCache(CuratorFramework client) throws Exception {
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/app2", true);

        //添加监听
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {

            @Override
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
                //获取子节点的改变类型
                PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();

                //判断监听子节点的改变类型是否为数据修改(UPDATE)
                if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)) {
                    System.out.println(pathChildrenCacheEvent);
                    //从监听事件对象中获取修改后的数据
                    byte[] data = pathChildrenCacheEvent.getData().getData();
                    System.out.println(new String(data));
                }
            }
        });

        pathChildrenCache.start();
        System.out.println("监听器已开启！");
        Thread.sleep(1000 * 120);
    }

    /**
     * Node Cache用来观察ZNode自身，如果ZNode节点本身被创建、更新、删除，那么Node Cache会更新缓存，并触发事件给注册的监听器。
     * Node Cache是通过NodeCache类来实现的，监听器对应的接口为NodeCacheListener。
     * @param client
     * @throws Exception
     */
    public void nodeCache(CuratorFramework client) throws Exception {
        //获取监听对象
        NodeCache nodeCache = new NodeCache(client, "/app2");

        //添加监听
        nodeCache.getListenable().addListener(new NodeCacheListener() {

            //监听回调函数，单个监听到节点发生增删改操作时会执行此方法
            @Override
            public void nodeChanged() throws Exception {
                String path = nodeCache.getPath();
                System.out.println(path + "节点收到了操作！");
                //获取当前节点更新后的数据
                byte[] data = nodeCache.getCurrentData().getData();
                System.out.println("更新后的数据为：" + new String(data));
            }
        });

        //开启监听，如果为true则开启监听器
        nodeCache.start(true);

        System.out.println("监听器已开启！");
        //让线程休眠30s(为了方便测试)
        Thread.sleep(1000 * 30);
    }

    /**
     * 可以看做是上两种的合体，Tree Cache观察的是ZNode及子节点。
     * @param client
     * @throws Exception
     */
    public void threeCache(CuratorFramework client) throws Exception {
        //指定监听对象
        TreeCache treeCache = new TreeCache(client, "/app2/op1");

        //添加监听器
        treeCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                System.out.println("子节点被改变！");
                System.out.println(treeCacheEvent);
            }
        });

        treeCache.start();
        System.out.println("监听器已开启！");
        Thread.sleep(1000 * 120);
    }
}
